﻿using System;
using System.IO;
using System.Text;
using System.Net;
using System.Xml;

using ECCIT;

namespace ECCIT.Net.SAML2
{
    public static class SAML
    {
        // Fields
        public const string Version = "2.0";

        // Methods
        public static string CreateID()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("_");
            builder.Append(Guid.NewGuid().ToString());
            return builder.ToString();
        }

        public static bool ToBoolean(string booleanString)
        {
            bool result = false;
            if (bool.TryParse(booleanString, out result))
            {
                return result;
            }
            if (booleanString == "0")
            {
                return false;
            }
            if (booleanString != "1")
            {
                throw new SerializationException("Failed to convert text to boolean: " + booleanString);
            }
            return true;
        }

        public static DateTime ToDateTime(string dateTimeString)
        {
            DateTime time;
            try
            {
                time = XmlConvert.ToDateTime(dateTimeString, XmlDateTimeSerializationMode.Utc);
            }
            catch (Exception exception)
            {
                throw new SerializationException("Failed to convert text to date/time: " + dateTimeString, exception);
            }
            return time;
        }

        public static string ToDateTimeString()
        {
            return ToDateTimeString(DateTime.UtcNow);
        }

        public static string ToDateTimeString(DateTime dateTime)
        {
            return XmlConvert.ToString(dateTime, XmlDateTimeSerializationMode.Utc);
        }

        public static XmlElement ToXmlElement(string xmlString)
        {
            XmlElement documentElement;
            try
            {
                documentElement = XmlHelper.LoadDocument(xmlString).DocumentElement;
            }
            catch (Exception exception)
            {
                throw new SerializationException("Failed to load XML: " + xmlString, exception);
            }
            return documentElement;
        }

        // Nested Types
        internal static class AttributeNames
        {
            // Fields
            public const string Action = "Action";
            public const string Address = "Address";
            public const string AffiliationOwnerID = "affiliationOwnerID";
            public const string AllowCreate = "AllowCreate";
            public const string AssertionConsumerServiceIndex = "AssertionConsumerServiceIndex";
            public const string AssertionConsumerServiceURL = "AssertionConsumerServiceURL";
            public const string AttributeConsumingServiceIndex = "AttributeConsumingServiceIndex";
            public const string AuthnInstant = "AuthnInstant";
            public const string AuthnRequestsSigned = "AuthnRequestsSigned";
            public const string Binding = "Binding";
            public const string CacheDuration = "cacheDuration";
            public const string Comparison = "Comparison";
            public const string Consent = "Consent";
            public const string ContactType = "contactType";
            public const string Count = "Count";
            public const string Decision = "Decision";
            public const string Destination = "Destination";
            public const string DNSName = "DNSName";
            public const string EntityID = "entityID";
            public const string ErrorURL = "errorURL";
            public const string ForceAuthn = "ForceAuthn";
            public const string Format = "Format";
            public const string FriendlyName = "FriendlyName";
            public const string ID = "ID";
            public const string Index = "index";
            public const string InResponseTo = "InResponseTo";
            public const string IsDefault = "isDefault";
            public const string IsPassive = "IsPassive";
            public const string IsRequired = "isRequired";
            public const string IssueInstant = "IssueInstant";
            public const string Language = "xml:lang";
            public const string Loc = "Loc";
            public const string Location = "Location";
            public const string Method = "Method";
            public const string Name = "Name";
            public const string NameFormat = "NameFormat";
            public const string NameQualifier = "NameQualifier";
            public const string Namespace = "Namespace";
            public const string NotBefore = "NotBefore";
            public const string NotOnOrAfter = "NotOnOrAfter";
            public const string ProtocolBinding = "ProtocolBinding";
            public const string ProtocolSupportEnumeration = "protocolSupportEnumeration";
            public const string ProviderID = "ProviderID";
            public const string ProviderName = "ProviderName";
            public const string ProxyCount = "ProxyCount";
            public const string Reason = "Reason";
            public const string Recipient = "Recipient";
            public const string Resource = "Resource";
            public const string ResponseLocation = "ResponseLocation";
            public const string SessionIndex = "SessionIndex";
            public const string SessionNotOnOrAfter = "SessionNotOnOrAfter";
            public const string SPNameQualifier = "SPNameQualifier";
            public const string SPProvidedID = "SPProvidedID";
            public const string Use = "use";
            public const string ValidUntil = "validUntil";
            public const string Value = "Value";
            public const string Version = "Version";
            public const string WantAssertionsSigned = "WantAssertionsSigned";
            public const string WantAuthnRequestsSigned = "WantAuthnRequestsSigned";
        }

        internal static class ElementNames
        {
            // Fields
            public const string Action = "Action";
            public const string AdditionalMetadataLocation = "AdditionalMetadataLocation";
            public const string Advice = "Advice";
            public const string AffiliateMember = "AffiliateMember";
            public const string AffiliationDescriptor = "AffiliationDescriptor";
            public const string Artifact = "Artifact";
            public const string ArtifactResolutionService = "ArtifactResolutionService";
            public const string ArtifactResolve = "ArtifactResolve";
            public const string ArtifactResponse = "ArtifactResponse";
            public const string Assertion = "Assertion";
            public const string AssertionConsumerService = "AssertionConsumerService";
            public const string AssertionIDRef = "AssertionIDRef";
            public const string AssertionIDRequest = "AssertionIDRequest";
            public const string AssertionIDRequestService = "AssertionIDRequestService";
            public const string AssertionURIRef = "AssertionURIRef";
            public const string Attribute = "Attribute";
            public const string AttributeAuthorityDescriptor = "AttributeAuthorityDescriptor";
            public const string AttributeConsumingService = "AttributeConsumingService";
            public const string AttributeProfile = "AttributeProfile";
            public const string AttributeQuery = "AttributeQuery";
            public const string AttributeService = "AttributeService";
            public const string AttributeStatement = "AttributeStatement";
            public const string AttributeValue = "AttributeValue";
            public const string Audience = "Audience";
            public const string AudienceRestriction = "AudienceRestriction";
            public const string AuthenticatingAuthority = "AuthenticatingAuthority";
            public const string AuthnAuthorityDescriptor = "AuthnAuthorityDescriptor";
            public const string AuthnContext = "AuthnContext";
            public const string AuthnContextClassRef = "AuthnContextClassRef";
            public const string AuthnContextDecl = "AuthnContextDecl";
            public const string AuthnContextDeclRef = "AuthnContextDeclRef";
            public const string AuthnQuery = "AuthnQuery";
            public const string AuthnQueryService = "AuthnQueryService";
            public const string AuthnRequest = "AuthnRequest";
            public const string AuthnStatement = "AuthnStatement";
            public const string AuthzDecisionQuery = "AuthzDecisionQuery";
            public const string AuthzDecisionStatement = "AuthzDecisionStatement";
            public const string AuthzService = "AuthzService";
            public const string BaseID = "BaseID";
            public const string Company = "Company";
            public const string Conditions = "Conditions";
            public const string ContactPerson = "ContactPerson";
            public const string EmailAddress = "EmailAddress";
            public const string EncryptedAssertion = "EncryptedAssertion";
            public const string EncryptedAttribute = "EncryptedAttribute";
            public const string EncryptedData = "EncryptedData";
            public const string EncryptedID = "EncryptedID";
            public const string EncryptedKey = "EncryptedKey";
            public const string EncryptionMethod = "EncryptionMethod";
            public const string EntitiesDescriptor = "EntitiesDescriptor";
            public const string EntityDescriptor = "EntityDescriptor";
            public const string Evidence = "Evidence";
            public const string Extensions = "Extensions";
            public const string GetComplete = "GetComplete";
            public const string GivenName = "GivenName";
            public const string IDPEntry = "IDPEntry";
            public const string IDPList = "IDPList";
            public const string IDPSSODescriptor = "IDPSSODescriptor";
            public const string Issuer = "Issuer";
            public const string KeyDescriptor = "KeyDescriptor";
            public const string LogoutRequest = "LogoutRequest";
            public const string LogoutResponse = "LogoutResponse";
            public const string ManageNameIDRequest = "ManageNameIDRequest";
            public const string ManageNameIDResponse = "ManageNameIDResponse";
            public const string ManageNameIDService = "ManageNameIDService";
            public const string NameID = "NameID";
            public const string NameIDFormat = "NameIDFormat";
            public const string NameIDMappingRequest = "NameIDMappingRequest";
            public const string NameIDMappingResponse = "NameIDMappingResponse";
            public const string NameIDMappingService = "NameIDMappingService";
            public const string NameIDPolicy = "NameIDPolicy";
            public const string NewEncryptedID = "NewEncryptedID";
            public const string NewID = "NewID";
            public const string OneTimeUse = "OneTimeUse";
            public const string Organization = "Organization";
            public const string OrganizationDisplayName = "OrganizationDisplayName";
            public const string OrganizationName = "OrganizationName";
            public const string OrganizationURL = "OrganizationURL";
            public const string PDPDescriptor = "PDPDescriptor";
            public const string ProxyRestriction = "ProxyRestriction";
            public const string RequestedAttribute = "RequestedAttribute";
            public const string RequestedAuthnContext = "RequestedAuthnContext";
            public const string RequesterID = "RequesterID";
            public const string Response = "Response";
            public const string RoleDescriptor = "RoleDescriptor";
            public const string Scoping = "Scoping";
            public const string ServiceDescription = "ServiceDescription";
            public const string ServiceName = "ServiceName";
            public const string SessionIndex = "SessionIndex";
            public const string SingleLogoutService = "SingleLogoutService";
            public const string SingleSignOnService = "SingleSignOnService";
            public const string SPSSODescriptor = "SPSSODescriptor";
            public const string Status = "Status";
            public const string StatusCode = "StatusCode";
            public const string StatusDetail = "StatusDetail";
            public const string StatusMessage = "StatusMessage";
            public const string Subject = "Subject";
            public const string SubjectConfirmation = "SubjectConfirmation";
            public const string SubjectConfirmationData = "SubjectConfirmationData";
            public const string SubjectLocality = "SubjectLocality";
            public const string SubjectQuery = "SubjectQuery";
            public const string Surname = "SurName";
            public const string TelephoneNumber = "TelephoneNumber";
            public const string Terminate = "Terminate";
        }

        public static class NamespaceURIs
        {
            // Fields
            public const string Assertion = "urn:oasis:names:tc:SAML:2.0:assertion";
            public const string Metadata = "urn:oasis:names:tc:SAML:2.0:metadata";
            public const string Protocol = "urn:oasis:names:tc:SAML:2.0:protocol";
        }

        public static class Prefixes
        {
            // Fields
            public const string MD = "md";
            public const string SAML = "saml";
            public const string SAMLP = "samlp";
        }
    }
}
